package com.cc.eds.process;

import com.cc.eds.model.DataInfo;
import com.cc.eds.model.Eds;
import com.cc.eds.model.EdsDataXml;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.security.WildcardTypePermission;
import javafx.beans.property.StringProperty;
import lombok.Getter;
import lombok.Setter;
import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.io.file.PathUtil;
import org.dromara.hutool.core.util.RuntimeUtil;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

/**
 * AbstractEdsRead
 *
 * @author aa
 * @version 1.0
 * @since 2025/2/8
 */
@Getter
@Setter
public abstract class AbstractEdsRead implements EdsRead {

    private EdsDataXml edsDataXml;

    private Path destPath;

    private StringProperty bcpFileNameLabel;
    private StringProperty dataCountLabel;

    public static final String USER_DIR = System.getProperty("user.dir");

    protected Path get7z() {
        if (FileUtil.isWindows()) {
            return Paths.get(USER_DIR, "7z", "7z.exe");
        } else {
            return Paths.get(USER_DIR, "7z", "7zz");
        }
    }

    @Override
    public boolean checkZip(File zipFile) {
        if (!FileUtil.exists(zipFile)) {
            return false;
        }
        String zipPath = FileUtil.getAbsolutePath(zipFile);
        String testFileCmd = get7z() + " t " + zipPath;
        String a = RuntimeUtil.execForStr(testFileCmd);
        return !a.contains("ERROR");
    }

    @Override
    public Path decompression(File zipFile) {
        String filename = FileNameUtil.getName(zipFile);
        String fileNamePrefix = filename.substring(0, filename.length() - 4);
        Path destPath = PathUtil.of(USER_DIR, "data", fileNamePrefix);
        if (!PathUtil.exists(destPath, false)) {
            PathUtil.mkdir(destPath);
        }
        String zipPath = FileUtil.getAbsolutePath(zipFile);
        String execCmd = get7z() + " x " + zipPath + " -o" + destPath + " -aos";
        String b = RuntimeUtil.execForStr(execCmd);
        if (!b.contains("ERROR")) {
            return destPath;
        }
        return null;
    }

    @Override
    public void loadXml(Path zipEtrDir) {
        // 通过index.xml文件解析
        Path xmlPath = zipEtrDir.resolve(Eds.ZIP_INDEX_XML_FILENAME);
        // 校验Xml文件是否存在
        if (!Files.exists(xmlPath)) {
            throw new RuntimeException(xmlPath + " not found");
        }
        this.edsDataXml = (EdsDataXml) xStream().fromXML(xmlPath.toFile());
        this.edsDataXml.setBcpDirPath(zipEtrDir);
    }

    @Override
    public List<Map<String, String>> read(Path zipEtrDir, String tableName) {
        if (this.edsDataXml == null) {
            return null;
        }
        DataInfo dataInfo = this.edsDataXml.getDataInfo(tableName);
        if (dataInfo == null) {
            return null;
        }
        List<Path> bcpList = this.edsDataXml.getBcpList(dataInfo);
        bcpFileNameLabel.set("当前文件名：" + PathUtil.getName(bcpList.get(0)));
        dataCountLabel.set("数据总条数：" + dataInfo.getBcpFileDataSize());
        List<Map<String, String>> dataList = new ArrayList<>();
        bcpList.forEach(path -> {
            if (PathUtil.exists(path, false)) {
                try (Stream<String> stream = Files.lines(path, dataInfo.getCharset())) {
                    stream.forEach((v) -> {
                        String[] oneLineData = dataInfo.getColumnSeparator().split(v, -1);
                        int minLength = Math.min(dataInfo.getBcpFieldNameArr().length, oneLineData.length);
                        Map<String, String> data = new HashMap<>();
                        for (int j = 0; j < minLength; j++) {
                            String fieldValue = oneLineData[j].trim();
                            String field = dataInfo.getBcpFieldNameZhArr()[j];
                            data.put(field, fieldValue);
                        }
                        dataList.add(data);
                    });
                } catch (Exception e) {
                    //log.error("解析BCP数据异常，文件路径：{}", path.toString(), e);
                }
            }
        });
        return dataList;
    }


    private static XStream xStream() {
        XStream xStream = new XStream();
        xStream.processAnnotations(EdsDataXml.class);
        xStream.addPermission(new WildcardTypePermission(new String[]{"com.cc.eds.**"}));
        return xStream;
    }

}
